11 调度
调度策略与调度类
实时进程:需要尽快执行返回结果。
普通进程:按照正常流程完成,优先级没实时进程高。
调度策略:优先级是一个数值,实时进程优先级范围是 0~99,普通进程优先级范围是 100~139。数值越小优先级越高。
实时调度策略
SCHED_FIFO:高优先级的进程可以抢占低优先级的进程,相同优先级的进程遵循先来先得。
SCHED_RR:轮流调度算法,采用时间片,相同优先级的任务当用完时间片会被放到队列尾部,以保证公平性,而高优先级的任务也是可以抢占低优先级的任务。
SCHED_DEADLINE:按照任务的 deadline 进行调度,选择其 deadline 距离当前时间点最近的那个任务,并调度它执行。
普通调度策略
SCHED_NORMAL:普通进程。
SCHED_BATCH:后台进程,几乎不需要和前端进行交互。
SCHED_IDLE:空闲时才跑的进程。
完全公平调度算法
CFS, Completely Fair Scheduling 完全公平调度。CFS 为每一个进程安排一个虚拟运行时间 vruntime,正在运行的进程随着时间的增长 vruntime 不断增大,没有得到执行的进程 vruntime 不变。
虚拟运行时间 vruntime += 实际运行时间 delta_exec * NICE_0_LOAD/ 权重
调度队列与调度实体
vruntime 经常在变,变了再插入这个数据结构,需要重新排序,使用红黑树平衡查询和快速更新。
调度类工作方式
在队列上操作任务,第一个成员变量是指针,指向下一个调度类。
调度时从优先级最高的调度类到优先级低的调度类依次执行,对于每种调度类有自己的实现。
- enqueue_task 向就绪队列中添加一个进程,当某个进程进入可运行状态时,调用这个函数;dequeue_task 将一个进程从就绪队列中删除;
- pick_next_task 选择接下来要运行的进程;
- put_prev_task 用另一个进程代替当前运行的进程;
- set_curr_task 用于修改调度策略;
- task_tick 每次周期性时钟到的时候,这个函数被调用,可能触发调度。
主动调度
- Btrfs 等待一个写入
- Tap 网络设备等待一个读取
schedule 函数的调用过程
- 取出任务队列 rq,task_struct *prev 指向这个 CPU 的任务队列上面正在运行的进程 curr
- 获取下一个任务,task_struct *next 指向下一个任务
- 当选出的继任者和前任不同,进行上下文切换,继任者进程正式进入运行